
#ifndef _INTERFACE_H_
#define _INTERFACE_H_

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define THIS _this(this)

#define BASE(name,super,maxPollSz) \
inline static name* _this(void *this) {return (name *)this;} \
static name *poll(name *ptr) { \
  static name *head = 0; \
  static sz = 0; \
  static maxSz = maxPollSz; \
  name *ret = 0; \
  if(!ptr) { \
    if(sz) { \
      ret = head; \
      head = head->next; \
      --sz; \
    } else { \
      ret = (name *)malloc(sizeof(name)); \
    } \
  } else { \
    if(sz==maxSz) { \
      free(ptr); \
    } else { \
      ptr->next = head; \
      head = ptr; \
      ++sz; \
    } \
  } \
} \
static name *CREATE() { \
  name *ptr = poll(0); \
  memset (ptr, 0, sizeof (name)); \
  ptr->interface = name##I(); \
  return ptr; \
} \
static void DESTROY(name *ptr) { \
  poll(ptr); \
} \
static inline super##FullInterface* SUPER() { \
  return (super##FullInterface *)super##I(); \
} \
static inline name##FullInterface* I() { \
  return (name##FullInterface *)name##I(); \
}

#define IMPL(ret, name,...) static ret (name)(void *this,##__VA_ARGS__)

#define FN(ret, name,...) ret (*name)(void *this,##__VA_ARGS__)

#define FNG(t, attr) FN(t, get_##attr)
#define FNS(t, attr) FN(void, set_##attr, t attr)
#define FNGS(t, attr) FNG(t, attr); FNS(t, attr)

#define BUILD_OBJ(name) \
typedef struct name##_Interface name##Interface; \
typedef struct \
{ \
  void *next; \
  name##Interface *interface; \
  name##_DEF \
} name; \
struct name##_Interface \
{ \
  name* (*create)(); \
  void (*destroy)(name *); \
  name##_SHARED \
}; \
name##Interface *name##I(); \
typedef struct { \
  name* (*create)(); \
  void (*destroy)(name *); \
  name##_SHARED \
  name##_EXCLUSIVE \
} name##FullInterface;



#define SET_ENTRY(n, f)  iTmp. n = f
#define ENTRY(f) SET_ENTRY(f,f)
#define MIRROR(f) SET_ENTRY(f,SUPER ()-> f)
#define ENTRYG(f) ENTRY(get_##f)
#define ENTRYS(f) ENTRY(set_##f)
#define ENTRYGS(f) ENTRYG(f), ENTRYS(f)

#define SETUP_IF(name, super, ...) \
name##Interface *name##I() { \
  static name##FullInterface iTmp = {.create = CREATE, .destroy = DESTROY}; \
  static name##FullInterface iResult; \
  static char init = 0; \
  if(!init) { \
    __VA_ARGS__; \
    init=1; \
    super##Interface *superI = super##I(); \
    memcpy(&iResult, superI, sizeof(super##Interface)); \
    void **src = (void **)&iTmp; \
    void **dst = (void **)&iResult; \
    int i; \
    for(i=0; i<sizeof(name##FullInterface); i+=4) { \
      if(*src) *dst = *src; \
      ++dst; ++src; \
    } \
  } \
  return &iResult; \
}



#define None_DEF
#define None_SHARED
#define None_EXCLUSIVE

typedef struct {
} None;

typedef struct {
} NoneInterface;

typedef struct {
} NoneFullInterface;

inline static NoneInterface *NoneI() {
  return 0;
}

#define GET(type, attribName) static type get_##attribName(void *this) { return THIS-> attribName; }

#define SET(type, attribName) static void set_##attribName(void *this, type attribName) { THIS-> attribName = attribName; }

#define GETSET(type, attribName) GET(type, attribName) SET(type, attribName)

#endif